package com.qidian.k12.service.impl;

import com.qidian.k12.dto.PageInfo;
import com.qidian.k12.mapper.TemplateItemMapper;
import com.qidian.k12.pojo.Template;
import com.qidian.k12.mapper.TemplateMapper;
import com.qidian.k12.pojo.TemplateItem;
import com.qidian.k12.service.TemplateService;
import com.qidian.k12.util.JsonTools;
import com.qidian.k12.util.K12Result;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

import javax.annotation.Resource;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * (Template)表服务实现类
 *
 * @author makejava
 * @since 2021-10-28 17:57:26
 */
@Service("templateService")
public class TemplateServiceImpl implements TemplateService {
    @Resource
    private TemplateMapper templateMapper;
    @Resource
    private TemplateItemMapper templateItemMapper;

    @Resource
    private StringRedisTemplate redisTemplate;


    @Override
    @Transactional
    public K12Result importTemplate(InputStream in, String fileName) {
        // 准备一个集合用来存储所有的导入成功的模版
        List<Template> templates = new ArrayList<>();
        //返回 模板 templates
        K12Result result = K12Result.ok(templates);

        StringBuilder sb = new StringBuilder();

        //创建xlsx
        Workbook workbook = null;
        try {
            if (fileName.endsWith("xlsx")) {
                workbook = new XSSFWorkbook(in);
            } else {
                workbook = new HSSFWorkbook(in);
            }
            //遍历 sheet
            Iterator<Sheet> sheets = workbook.iterator();
            while (sheets.hasNext()) {
                //
                Map parseSheetResult = parseSheet(sheets.next());
                // 返回值
                if (!new Boolean(parseSheetResult.get("result").toString())) {
                    // 记录错误信息
                    sb.append(parseSheetResult.get("msg"));
                    result.setStatus(K12Result.ResultStatus.OK_PART);
                } else {
                    // 将返回的结果加入到templates集合中。  返回页面数据
                    sb.append(parseSheetResult.get("msg"));
                    templates.add((Template) parseSheetResult.get("template"));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        //设置状态
        result.setMsg(sb.toString());
        //返回结果
        return result;
    }

    //sheet 成功返回true，否则返回false
    private Map parseSheet(Sheet sheet) {
        Map map = new HashMap();

        map.put("result", true);
        map.put("msg", "保存成功");
        //
        int lastRowNum = sheet.getLastRowNum();
        //创建一个模板 插入数据
        Template template = new Template();
        //第二行数据
        Row row = sheet.getRow(1);
        //模板名字
        try {
            String templateName = row.getCell(1).toString();
            System.out.println("模板名称：" + templateName);
            //校验 失败 解析失败
            if (template.equals("")) {
                throw new RuntimeException("模板名不能为空");
            }
            //设置名字
            template.setTemplateName(templateName);
        } catch (Exception e) {
            e.printStackTrace();
            map.put("reslut", false);
            map.put("msg", "模板解析失败，sheet的索引是:" + sheet.getSheetName());
            return map;
        }
        //模板描述
        try {
            String templateDesc = row.getCell(2).toString();
            System.out.println("模版描述：" + templateDesc);
            template.setTemplateDesc(templateDesc);
        } catch (Exception e) {
        }

        //补全数据
        Date date = new Date();
        template.setCreateTime(date);
        template.setModifyTime(date);
        template.setTemplateStatus(1);
        // 插入模板
        K12Result r = insert(template);
        if (r.getStatus() == 200) {
            map.put("msg", "<p>" + sheet.getSheetName() + "中的模版[" + sheet.getSheetName() + "]保存成成功</p>");

            //获取 templateId
            Template t1 = (Template) r.getData();
            //System.out.println("templateId:" + t1.getTemplateId());
            template.setTemplateId(t1.getTemplateId());

            //模版已经保存成功,将template加入map
            map.put("template", template);

            // 解析模版项
            List<TemplateItem> items = new ArrayList<>();
            for (int index = 4; index <= lastRowNum; index++) {
                //解析一行
                Row itemRow = sheet.getRow(index);
                //创建模板项
                TemplateItem item = new TemplateItem();
                item.setTemplateId(template.getTemplateId());
                try {
                    String itemName = itemRow.getCell(1).toString();
                    item.setItemName(itemName);
                    float itemProportion = new Float(itemRow.getCell(2).toString());
                    item.setItemProportion((int) (itemProportion));
                    float itemMaxScore = new Float(itemRow.getCell(3).toString());
                    item.setItemMaxScore((int) (itemMaxScore));
                    System.out.println(itemName + ":" + itemProportion + ":" + itemMaxScore);
                    // 补全其他属性
                    item.setCreateTime(date);
                    item.setModifyTime(date);
                    item.setItemStatus(1);
                    // 保存item
                    items.add(item);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            //批量保存
            if (templateItemMapper.insertBatch(items) > 0) {
                template.setTemplateItems(items);
            }
        } else if (r.getStatus() == 505) {
            map.put("result", false);// 模版解析失败
            map.put("msg", "<p>" + sheet.getSheetName() + "中的模版[" + template.getTemplateName() + "]名称重复<p/>");
            return map;
        } else {
            map.put("result", false);// 模版解析失败
            map.put("msg", "模版解析失败,sheet的索引是:" + sheet.getSheetName());
            return map;
        }

        return map;
    }

    @Override
    public K12Result queryByName(String templateName) {
        return K12Result.ok(templateMapper.queryByName1(templateName));
    }

    /**
     * @param map 查询条件
     *            {page:1,rows:10,templateName:"231",timeStart:"",timeEnd:"",templateStatus:0}
     * @return
     */
    @Override
    public PageInfo<Template> queryByPage(Map map) {

        PageInfo<Template> pageInfo = new PageInfo<>();
        int page = new Integer(map.get("page").toString());
        int rows = new Integer(map.get("row").toString());
        pageInfo.setPage(page);
        pageInfo.setRow(rows);
        //总条数
        int total = templateMapper.total(map);
        pageInfo.setTotal(total);
        int maxPageNum = (int) (Math.ceil(total * 1.0 / rows));
        pageInfo.setMaxPageNun(maxPageNum);
        //计算分页栏位置
        int pageStart = 1;
        int pageEnd = 10;
        if (page - 4 > 1) {
            pageStart = page - 4;
        }
        if (page + 5 > maxPageNum) {
            pageEnd = maxPageNum;
        }
        pageInfo.setPageStart(pageStart);
        pageInfo.setPageEnd(pageEnd);
        //数据 放在 pageInfo.data
        pageInfo.setData(templateMapper.queryByPage(map));

        return pageInfo;
    }


    /**
     * 通过ID查询单条数据
     *
     * @param templateId 主键
     * @return 实例对象
     */
    @Override
    public Template queryById(Long templateId) {
        // key
        String key = "template_" + templateId;
        //缓存中查询数据
        if (redisTemplate.hasKey(key)) {
            //获得
            String templateJson = redisTemplate.opsForValue().get(key);
            if (templateJson != null && !"".equals(templateJson)) {
                try {
                    //使用工具类  将json 转为 对象
                    Template template = JsonTools.string2Obj(templateJson, Template.class);
                    //返回结果
                    return template;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        //如果 缓存中 没查到
        // 数据库中查询
        Template template = templateMapper.queryById(templateId);
        template.setTemplateItems(templateItemMapper.queryByTempId(templateId));
        //工具类转为json
        String json = JsonTools.obj2String(template);
        //把json数据放到缓存中
        redisTemplate.opsForValue().set(key, json);
        //设置存活时间
        redisTemplate.expire(key, 30, TimeUnit.MINUTES);
        //结果返回
        return template;
    }


    /**
     * 新增数据
     *
     * @param template 实例对象
     * @return 实例对象
     */
    @Override
    public K12Result insert(Template template) {
        K12Result result = K12Result.error();
        //
        if (template != null && template.getTemplateName() != null && "".equals(template.getTemplateName())) {
            //查询
            List<Template> templates = templateMapper.searchByName(template.getTemplateName());
            //数据不存在 或查询出多个数据
            if (templates != null || templates.size() > 0) {
                return K12Result.dataEXists();
            }
        }
        //补全数据
        Date date = new Date();
        template.setCreateTime(date);
        template.setModifyTime(date);
        template.setTemplateStatus(1);

        int res = this.templateMapper.insert(template);
        if (res == 1) {
            result = K12Result.ok();
            result.setData(template);
            return result;
        }

        return result;
    }

    /**
     * 修改数据
     *
     * @param template 实例对象
     * @return 实例对象
     */
    @Override
    public K12Result update(Template template) {
        //缓存同步 延迟双删
        //5000次测试的访问耗时为：456

        //先删缓存   再更新数据库  再删缓存
        String key = "template_" + template.getTemplateId();

        redisTemplate.delete(key);

        K12Result result = K12Result.error();
        //补全数据
        Date date = new Date();
        template.setModifyTime(date);
        if (this.templateMapper.update(template) == 1) {
            result = K12Result.ok();
            //查询结果 返回
            result.setData(this.queryById(template.getTemplateId()));

            // 修改完成，延迟 600毫秒，再次删除缓存
            // 开启一个线程，处理这个任务。  // 开启一个任务
            //  放在一个线程池中执行   注意：这个任务必须立刻执行，不能缓存。
            // 这里就涉及到线程池的相关问题:
            // 1、任务不能缓存（SynchronousQueue）。
            // 2、处理好拒绝策略(重复测试)。
            new Thread(() -> {
                try {
                    redisTemplate.delete(key);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }

        return result;
    }

    /**
     * 通过主键删除数据
     *
     * @param templateId 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Long templateId) {
        return this.templateMapper.deleteById(templateId) > 0;
    }
}
